// Copyright 2012, Vanya Davidenko.
// Используемая кодировка: UTF-8.

#ifndef LIBV_BOOST_SERIALIZATION_H_
#define LIBV_BOOST_SERIALIZATION_H_

#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/interprocess/streams/vectorstream.hpp>
#include <boost/scope_exit.hpp>
#include <boost/serialization/export.hpp>
#include <libv/static_assert.h>
#include <istream>
#include <ostream>
#include <vector>



namespace libv {

template<class T>
inline ::std::vector<char> Serialize(const T& t) {
    boost::interprocess::basic_ovectorstream< ::std::vector<char>,
                                              ::std::char_traits<char> > s;
    {
        boost::archive::binary_oarchive boa(static_cast< ::std::ostream& >(s));
        boa << t;
    }

    ::std::vector<char> result;
    s.swap_vector(result);
    return result;
}



template<class T>
inline T Deserialize(const ::std::vector<char>& buf) {
    boost::interprocess::basic_ivectorstream< ::std::vector<char>,
                                              ::std::char_traits<char> > s;
    T result;
    {
        // Неудачный интерфейс у basic_ivectorstream.
        // Но за счет BOOST_SCOPE_EXIT метод 100% не испортит const buf.
        ::std::vector<char>* pbuf = const_cast< ::std::vector<char>* >(&buf);
        s.swap_vector(*pbuf);

        BOOST_SCOPE_EXIT((&s)(&pbuf)) {
            s.swap_vector(*pbuf);
        } BOOST_SCOPE_EXIT_END

        
        boost::archive::binary_iarchive bia(static_cast< ::std::istream& >(s));
        bia >> result;
    }
    return result;
}

}  // libv

#endif  // LIBV_BOOST_SERIALIZATION_H_
